/******************************************************************************
*
* This file is part of FreeTrack (http://code.google.com/p/qtfreetrack).
* BY Willy Gardiol (willy@gardiol.org)
*
* FreeTrack is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FreeTrack is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Foobar.  If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/

#include "freetrackwidget.h"
#include "layertrackconfig.h"
#include "layertrack.h"
#include "oauthmanager.h"
#include "configwidget.h"
#include "trackwaypoint.h"
#include "ftwidgetlist.h"
#include "layermanager.h"
#include "ftpushbutton.h"
#include "ftlabel.h"
#include "fttabwidget.h"
#include "fthelpwidget.h"

extern ConfigWidget* conf;

QMap<QString, QString> breadcrumbs_list_activities;
QMap<QString, QMap<QString,QString> > breadcrumbs_list_bundles;

LayerTrackConfig::LayerTrackConfig(QWidget* parent, LayerTrack *layer) :
    FreeTrackWidget(parent),
    track(layer)
{
    oauth = new OauthManager(this);

    tabs = new FTTabWidget();
    connect( tabs, SIGNAL(currentChanged()),
             this, SLOT(changeTab()));

    // General config tab
    tab_setup = new QWidget();
    title_label = new FTLabel( tr("Track title:"));
    title = new QLineEdit( track->getTitle() );
    description_label = new FTLabel( tr("Track description:"));
    description = new QLineEdit( track->getDescription() );
    color_label = new FTLabel( tr("Track color and size:"));
    color_button = new FTPushButton(QIcon(), QSize(64,64) );
    color_button->setMinimumWidth(48);
    color_button->setMinimumHeight(48);
    setColor( layer->getColor() );
    size_bar = new QScrollBar( Qt::Horizontal );
    size_bar->setMinimum( TRACK_MIN_SIZE );
    size_bar->setMaximum( TRACK_MAX_SIZE );
    size_bar->setValue( track->getSize() );
    size_bar->setMinimumHeight(48);
    connect( color_button, SIGNAL(clicked()),
              this, SLOT(selectColor() ));


    // Waypoint tab
    tab_waypoints = new QWidget();
    waypoints_list = new FTWidgetList();
    waypoints_list->setActions( false, track->isLiveTrack() );
    connect( waypoints_list, SIGNAL(itemDeleted(int)),
                       this, SLOT(deleteWaypoint(int)) );

    foreach (int key, track->listWaypointIDs())
    {
        QString n,d;
        track->getWaypoint( key, n,d );
        FTLabel* wp_n_l = new FTLabel( tr("N")+":" );
        QLineEdit* wp_n = new QLineEdit(n);
        FTLabel* wp_d_l = new FTLabel( tr("D")+":" );
        QLineEdit* wp_d = new QLineEdit(d);
        // Insert into hashes
        waypoint_names.insert( key, wp_n );
        waypoint_descriptions.insert( key,wp_d );

        // Build the widget to show in the list
        QWidget* tmp = new QWidget();
        QVBoxLayout* vgrid = new QVBoxLayout();
        QHBoxLayout* hgrid = new QHBoxLayout();
        hgrid->addWidget( wp_n_l );
        hgrid->addWidget( wp_n );
        vgrid->addLayout( hgrid );
        hgrid = new QHBoxLayout();
        hgrid->addWidget( wp_d_l );
        hgrid->addWidget( wp_d );
        vgrid->addLayout( hgrid );
        tmp->setLayout( vgrid );
        waypoints_list->appendWidget( key, tmp );
        if ( !track->isLiveTrack() )
        {
            wp_n->setReadOnly(true);
            wp_d->setReadOnly(true);
        }
    }

    // Tab breadcrumbs
    tab_breadcrumbs = new QWidget();
    breadcrumbs_activities = new QComboBox();
    connect( breadcrumbs_activities, SIGNAL(currentIndexChanged(QString)),
                               this, SLOT(breadcrumbsSelectActivity(QString)));
    breadcrumbs_bundles = new QComboBox();
    breadcrumbs_reload_activities = new FTPushButton( tr("Reload activities..."));
    connect( breadcrumbs_reload_activities, SIGNAL(clicked()),
             this, SLOT(breadcrumbsReloadActivities()));
    breadcrumbs_new_bundle = new FTPushButton( tr("Create new bundle...") );
    connect( breadcrumbs_new_bundle, SIGNAL(clicked()),
             this, SLOT(breadcrumbsNewBundle()));
    breadcrumbs_export = new FTPushButton( tr("Export track!") );
    connect( breadcrumbs_export, SIGNAL(clicked()),
             this, SLOT(breadcrumbsExport()));
    breadcrumbs_activities_label = new FTLabel( tr("Activities:"));
    breadcrumbs_bundles_label = new FTLabel( tr("Bundles:"));
    breadcrumbs_help = new FTHelpWidget(
     tr(  "<center|b>www.gobreadcrumbs.com</center>"\
          "<justify>GoBreadcrumbs is a nice and free service that allows you to upload, store and share your "\
          "GPS tracks. (actually it lets you do much more, but its out of the scope of FreeTrack)</justify>"\
      "<justify>FreeTrack lets you can upload your tracks to it using your phone web capabilities. In this way, you can "\
      "safely store your tracks on-line. "\
      "To do this, first you need to register with www.gobreadcrumbs.com and obtain a valid login/password, then "\
      "you need to authorize FreeTrack to access www.gobreadcrumbs.com. "\
      "This authorization process is divided in two steps: requesting authorization and setting a PIN in Freetrack. "\
      "Go to the configuration page and tab the breadcrumbs button. FreeTrack will contact the website and request a "\
      "preliminary autentication which will switch on the phone browser where you will have to login to your account "\
      "and write down the PIN number that will be displayed. "\
      "Now switch back to FreeTrack and insert that PIN number. If everything is OK, you will be authorized to use "\
      "the online export to www.gobreadcrumbs.com once for all.</justify>"\
      "<justify>To actually upload a track, you must select an 'activity'' and a 'bundle' (you can also "\
      "create a new bundle) before tapping the export button.</justify>"\
      "<center|b>please note: exporting to breadcrumbs, authenticating, reading the activities, creating bundles will "\
      "use your internet connection. Make sure you have a WiFi spot or you might incour in charges for mobile "\
      "data traffic.</center>" ));

    tabs->addTab( tab_setup, tr("configure the track"));
    tabs->addTab( tab_waypoints, tr("edit waypoints"));
    tabs->addTab( tab_breadcrumbs, tr("Export to GoBreadcrumbs"));

    // Save and cancel buttons
    save_button = new FTPushButton( QIcon( ":/icons/save.png"), BUTTON_SIZE);
    connect( save_button, SIGNAL(clicked()),
             this, SLOT(updateTrack()) );
    cancel_button = new FTPushButton( QIcon( ":/icons/cancel.png"), BUTTON_SIZE);
    connect( cancel_button, SIGNAL(clicked()),
             this, SIGNAL(accept()));

    QWidget* bts = new QWidget();
    QHBoxLayout* hgrid = new QHBoxLayout(bts);
    hgrid->addStretch();
    hgrid->addWidget( save_button );
    hgrid->addStretch();
    hgrid->addWidget( cancel_button );
    hgrid->addStretch();
    tabs->addExtra( bts );

}

LayerTrackConfig::~LayerTrackConfig()
{
    delete oauth;
}

void LayerTrackConfig::deleteWaypoint(int key)
{
    if ( !waypoint_names.contains(key) )
        return;
    // Widgets gets deleted inside the list
    waypoint_names.take( key );
    waypoint_descriptions.take( key );
    deleted_waypoints.append( key );
}

void LayerTrackConfig::selectColor()
{
    setColor( QColorDialog::getColor( color, this, tr("Select track color") ) );
}

void LayerTrackConfig::setColor(QColor c)
{
    color = c;
    color_button->setBackground( QBrush( c, Qt::SolidPattern ));
}

void LayerTrackConfig::updateTrack()
{
    bool modified = false;
    if ( track->getTitle() != title->text() )
    {
        track->setTitle( title->text() );
        modified = true;
    }

    if ( track->getDescription() != description->text() )
    {
        track->setDescription( description->text() );
        modified = true;
    }

    if ( size_bar->value() != track->getSize() )
    {
        track->setSize( size_bar->value() );
        modified = true;
    }

    if ( color != track->getColor() )
    {
        track->setColor( color );
        modified = true;
    }

    if ( track->isLiveTrack() )
    {
        foreach (int key, deleted_waypoints )
            track->removeWaypoint( key );

        // Update all remaining waypoints
        foreach (int key, waypoint_names.keys() )
            track->updateWaypoint( key, waypoint_names.value(key)->text(), waypoint_descriptions.value(key)->text() );
    }

    if ( modified )
        track->saveExtra();
    if ( track->isModified() )
        track->saveTrack();

    emit accept();
}


void LayerTrackConfig::changeTab()
{
    if ( tabs->currentWidget() == tab_breadcrumbs )
    {
        if ( !conf->breadcrumbsAuthorized() )
        {
            QMessageBox::information( this,
                                      tr("www.gobreadcrumbs.com"),
                                      tr("You must authorize FreeTrack with www.breadcrumbs.com from the configure page!") );
            tabs->showIndex();
        }
        else
            breadcrumbsLoadActivities();
    }
}


void LayerTrackConfig::breadcrumbsReloadActivities()
{
    if ( QMessageBox::question( this,
                              tr("Reload activities?"),
                              tr("Do you want to reload the activities list?"),
                              QMessageBox::Yes|QMessageBox::No,
                              QMessageBox::NoButton ) == QMessageBox::Yes )
    {
        breadcrumbs_list_activities.clear();
        breadcrumbsLoadActivities();
    }
}


void LayerTrackConfig::breadcrumbsSelectActivity(QString activity)
{
    QString activity_id = breadcrumbs_list_activities.value( activity );
    if ( activity_id.isEmpty() )
        return;
    QMap<QString,QString> bundles = breadcrumbs_list_bundles.value( activity_id );
    breadcrumbs_bundles->clear();
    if ( bundles.count() > 0 )
        breadcrumbs_bundles->addItems( bundles.keys( ) );
}

void LayerTrackConfig::breadcrumbsLoadActivities(bool nested)
{
    if ( breadcrumbs_list_activities.count() > 0 )
    {
        breadcrumbs_activities->clear();
        breadcrumbs_bundles->clear();
        breadcrumbs_activities->addItems(breadcrumbs_list_activities.keys());
        return;
    }
    if ( nested )
    {
        QMessageBox::information( this,
                                  tr("www.gobreadcrumbs.com"),
                                  tr("Unable to load activities and bundles!") );
        return;
    }

    QByteArray rawActivities = oauth->getData("v1/activities.xml",
                                              OauthParams(),
                                              tr("Loading activities..."));

    QByteArray rawBundles = oauth->getData("v1/bundles.xml",
                                              OauthParams(),
                                              tr("Loading bundles..."));

    breadcrumbs_list_activities.clear();

    QXmlStreamReader stream_a(rawActivities);
    QString id, name;
    bool in_activity = false;
    QList<QString> valid_activities;

    while (!stream_a.atEnd() && !stream_a.hasError() )
    {
        if ( stream_a.isStartElement() && (stream_a.name() == "activity") )
        {
            id = name = "";
            in_activity = true;
        }
        while ( in_activity && !stream_a.atEnd() && ! stream_a.hasError() )
        {
            stream_a.readNext();
            if ( stream_a.isStartElement() && (stream_a.name() == "id") && (id == "" ) )
            {
                stream_a.readNext();
                id = stream_a.text().toString();
            }
            if ( stream_a.isStartElement() && (stream_a.name() == "name") && (name == "" ) )
            {
                stream_a.readNext();
                name = stream_a.text().toString();
            }
            if ( stream_a.isEndElement() && stream_a.name() == "activity" )
            {
                in_activity = false;
                if ( !id.isEmpty() && !name.isEmpty() )
                {
                    breadcrumbs_list_activities.insert( name, id );
                    breadcrumbs_list_bundles.insert( id, QMap<QString,QString>() );
                    valid_activities.append( id );
                }
            }
        }
        stream_a.readNext();
    }

    QXmlStreamReader stream_b(rawBundles);
    QString activityId;
    bool in_bundle = false;
    QString id_activity;
    while (!stream_b.atEnd() && !stream_b.hasError() )
    {
        if ( stream_b.isStartElement() && (stream_b.name() == "bundle") )
        {
            id_activity = id = name = "";
            in_bundle = true;
        }
        while ( in_bundle && !stream_b.atEnd() && ! stream_b.hasError() )
        {
            stream_b.readNext();
            if ( stream_b.isStartElement() && (stream_b.name() == "id") && (id == "" ) )
            {
                stream_b.readNext();
                id = stream_b.text().toString();
            }
            if ( stream_b.isStartElement() && (stream_b.name() == "activity-id") && (id_activity == "" ) )
            {
                stream_b.readNext();
                id_activity = stream_b.text().toString();
            }
            if ( stream_b.isStartElement() && (stream_b.name() == "name") && (name == "" ) )
            {
                stream_b.readNext();
                name = stream_b.text().toString();
            }
            if ( stream_b.isEndElement() && stream_b.name() == "bundle" )
            {
                in_bundle = false;
                if ( !id.isEmpty() && !name.isEmpty() && !id_activity.isEmpty() )
                {
                    if ( valid_activities.contains( id_activity ) )
                    {
                        breadcrumbs_list_bundles[id_activity].insert( name, id );
                    }
                }
            }
        }
        stream_b.readNext();
    }
    breadcrumbsLoadActivities(true);
}

void LayerTrackConfig::breadcrumbsExport()
{
    QString activity = breadcrumbs_activities->currentText();
    QString bundle = breadcrumbs_bundles->currentText();
    QString activity_id = breadcrumbs_list_activities.value( activity );
    QString bundle_id = breadcrumbs_list_bundles[activity_id].value( bundle );
#ifdef Q_OS_SYMBIAN
    if ( activity_id.isEmpty() )
    {
        QMessageBox::information( this,
                                  tr("www.gobreadcrumbs.com"),
                                  tr("Please select an activity") );
        return;
    }
    if ( bundle_id.isEmpty() )
    {
        QMessageBox::information( this,
                                  tr("www.gobreadcrumbs.com"),
                                  tr("Please select or create a bundle!") );
        return;
    }
#endif

    OauthParams params;

    params.insert( "import_type", "GPX" );
    params.insert( "bundle_id", bundle_id.toAscii() );
    params.insert( "public", "false" );

    QByteArray xml;
    track->toXml(&xml);

    params.insert("gpx", xml.toPercentEncoding() );
    oauth->postData("v1/tracks",
                        params,
                        tr("Uploading track..."));

    if ( !oauth->getError() )
    {
        QMessageBox::information( this,
                                  tr("www.gobreadcrumbs.com"),
                                  tr("Upload successful!") );
    }
    else
        QMessageBox::information( this,
                                  tr("www.gobreadcrumbs.com"),
                                  tr("Unable to upload track!") );
}

void LayerTrackConfig::breadcrumbsNewBundle()
{
    bool ok = false;
    QString activity = breadcrumbs_activities->currentText();
    int idx = breadcrumbs_activities->currentIndex();
    QString bundle = QInputDialog::getText(this,
                                            tr("New bundle"),
                                            tr("New bundle title:"),
                                            QLineEdit::Normal,
                                            QString(),
                                            &ok);
    if ( ok && !activity.isEmpty() )
    {
        OauthParams params;
        params.insert("name", bundle.toAscii().toPercentEncoding() );
        params.insert("activity_id", breadcrumbs_list_activities.value(activity).toAscii() );
        oauth->postData("v1/bundles.xml",params,tr("Creating bundle..."));
        if ( !oauth->getError() )
        {
            breadcrumbs_list_activities.clear();
            QMessageBox::information( this,
                                      tr("www.gobreadcrumbs.com"),
                                      tr("Created successfully!") );
            breadcrumbsLoadActivities();
            breadcrumbs_activities->setCurrentIndex(idx);
            idx = breadcrumbs_bundles->findText( bundle,
                                               Qt::MatchExactly );
            breadcrumbs_bundles->setCurrentIndex(idx);
        }
        else
            QMessageBox::information( this,
                                      tr("www.gobreadcrumbs.com"),
                                      tr("Unable to create bundle!") );
    }
}


QLayout* LayerTrackConfig::createHorizontal()
{
    QHBoxLayout* grid = new QHBoxLayout();
    grid->addWidget( tabs );
    if ( tab_setup->layout() )
        delete tab_setup->layout();
    QVBoxLayout* setupGrid = new QVBoxLayout();
    setupGrid->addWidget( title_label );
    setupGrid->addWidget( title );
    setupGrid->addWidget( description_label );
    setupGrid->addWidget( description );
    setupGrid->addWidget( color_label );
    QHBoxLayout* colGrid = new QHBoxLayout();
    colGrid->addWidget( color_button );
    colGrid->addWidget( size_bar );
    setupGrid->addLayout( colGrid );
    setupGrid->addStretch();
    tab_setup->setLayout( setupGrid );

    if ( tab_waypoints->layout() )
        delete tab_waypoints->layout();
    QVBoxLayout* waypointGrid = new QVBoxLayout();
    waypointGrid->addWidget( waypoints_list );
/*    for ( int w = 0; w < n_waypoints; w++ )
    {
        waypointGrid->addWidget( wp_names_labels.at(w) );
        waypointGrid->addWidget( waypoint_names.at(w) );
        waypointGrid->addWidget( wp_description_labels.at(w) );
        waypointGrid->addWidget( waypoint_descriptions.at(w) );
    }
    waypointGrid->addStretch();*/
    tab_waypoints->setLayout( waypointGrid );

    if ( tab_breadcrumbs->layout() )
        delete tab_breadcrumbs->layout();
    QVBoxLayout* breadcrumbsGrid = new QVBoxLayout();
    breadcrumbsGrid->addWidget( breadcrumbs_activities_label );
    breadcrumbsGrid->addWidget( breadcrumbs_activities );
    breadcrumbsGrid->addWidget( breadcrumbs_reload_activities );
    breadcrumbsGrid->addWidget( breadcrumbs_bundles_label );
    breadcrumbsGrid->addWidget( breadcrumbs_bundles );
    breadcrumbsGrid->addWidget( breadcrumbs_new_bundle );
    QHBoxLayout* bgr = new QHBoxLayout();
    bgr->addWidget( breadcrumbs_export );
    bgr->addWidget( breadcrumbs_help );
    breadcrumbsGrid->addLayout( bgr );
    breadcrumbsGrid->addStretch();
    tab_breadcrumbs->setLayout( breadcrumbsGrid );

    return grid;
}

QLayout* LayerTrackConfig::createVertical()
{
    QVBoxLayout* grid = new QVBoxLayout();
    grid->addWidget( tabs );
    if ( tab_setup->layout() )
        delete tab_setup->layout();
    QVBoxLayout* setupGrid = new QVBoxLayout();
    setupGrid->addWidget( title_label );
    setupGrid->addWidget( title );
    setupGrid->addWidget( description_label );
    setupGrid->addWidget( description );
    setupGrid->addWidget( color_label );
    QHBoxLayout* colGrid = new QHBoxLayout();
    colGrid->addWidget( color_button );
    colGrid->addWidget( size_bar );
    setupGrid->addLayout( colGrid );
    setupGrid->addStretch();
    tab_setup->setLayout( setupGrid );

    if ( tab_waypoints->layout() )
        delete tab_waypoints->layout();
    QVBoxLayout* waypointGrid = new QVBoxLayout();
    waypointGrid->addWidget( waypoints_list );
    tab_waypoints->setLayout( waypointGrid );

    if ( tab_breadcrumbs->layout() )
        delete tab_breadcrumbs->layout();
    QVBoxLayout* breadcrumbsGrid = new QVBoxLayout();
    breadcrumbsGrid->addWidget( breadcrumbs_activities_label );
    breadcrumbsGrid->addWidget( breadcrumbs_activities );
    breadcrumbsGrid->addWidget( breadcrumbs_reload_activities );
    breadcrumbsGrid->addWidget( breadcrumbs_bundles_label );
    breadcrumbsGrid->addWidget( breadcrumbs_bundles );
    breadcrumbsGrid->addWidget( breadcrumbs_new_bundle );
    QHBoxLayout* bgr = new QHBoxLayout();
    bgr->addWidget( breadcrumbs_export );
    bgr->addWidget( breadcrumbs_help );
    breadcrumbsGrid->addLayout( bgr );
    breadcrumbsGrid->addStretch();
    tab_breadcrumbs->setLayout( breadcrumbsGrid );

    return grid;
}
